/*
 * @Author: xiaosihan 
 * @Date: 2024-08-29 11:49:11 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-08-29 14:19:53
 */

import { PointsMaterial, PointsMaterialParameters, Vector3, WebGLProgramParametersWithUniforms, WebGLRenderer } from "three";


// 模型粒子的材质
export default class MeshPointsMaterial extends PointsMaterial {

    constructor(parameters?: PointsMaterialParameters) {
        super(parameters);
    }

    vertexShader = `
        uniform float progress;
        uniform float size;
        uniform vec3 v3size;
        uniform vec3 center;
        uniform float scale;
        #include <common>
        #include <color_pars_vertex>
        #include <fog_pars_vertex>
        #include <morphtarget_pars_vertex>
        #include <logdepthbuf_pars_vertex>
        #include <clipping_planes_pars_vertex>
        #ifdef USE_POINTS_UV
            varying vec2 vUv;
            uniform mat3 uvTransform;
        #endif
        void main() {
            #ifdef USE_POINTS_UV
                vUv = ( uvTransform * vec3( uv, 1 ) ).xy;
            #endif
            #include <color_vertex>
            #include <morphinstance_vertex>
            #include <morphcolor_vertex>
            #include <begin_vertex>
            #include <morphtarget_vertex>
            
            vec4 mvPosition = vec4( transformed, 1.0 );
            #ifdef USE_BATCHING
                mvPosition = batchingMatrix * mvPosition;
            #endif
            #ifdef USE_INSTANCING
                mvPosition = instanceMatrix * mvPosition;
            #endif

            gl_PointSize = size;

            float px = ((progress - 0.5) * v3size.x);
            float distance = abs(px - mvPosition.x);
            if(px < mvPosition.x && distance < 0.3){
                mvPosition.z *= (1.0 + distance * 10.0 );
                mvPosition.y *= (1.0 + distance * 10.0 );
                mvPosition.x += distance;
            }else{
                gl_PointSize = 0.0;
            }
            
            mvPosition = modelViewMatrix * mvPosition;
            gl_Position = projectionMatrix * mvPosition;

            #ifdef USE_SIZEATTENUATION
                bool isPerspective = isPerspectiveMatrix( projectionMatrix );
                if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );
            #endif
            #include <logdepthbuf_vertex>
            #include <clipping_planes_vertex>
            #include <worldpos_vertex>
            #include <fog_vertex>
        }
    `;

    fragmentShader = `
        uniform vec3 diffuse;
        uniform float opacity;
        #include <common>
        #include <color_pars_fragment>
        #include <map_particle_pars_fragment>
        #include <alphatest_pars_fragment>
        #include <alphahash_pars_fragment>
        #include <fog_pars_fragment>
        #include <logdepthbuf_pars_fragment>
        #include <clipping_planes_pars_fragment>
        void main() {
            vec4 diffuseColor = vec4( diffuse, opacity );
            #include <clipping_planes_fragment>
            vec3 outgoingLight = vec3( 0.0 );
            #include <logdepthbuf_fragment>
            #include <map_particle_fragment>
            #include <color_fragment>
            #include <alphatest_fragment>
            #include <alphahash_fragment>
            outgoingLight = diffuseColor.rgb;
            #include <opaque_fragment>
            #include <tonemapping_fragment>
            #include <colorspace_fragment>
            #include <fog_fragment>
            #include <premultiplied_alpha_fragment>
        }
    `;

    //粒子散开的进度
    progress = -Infinity;

    v3size = new Vector3(Infinity, Infinity, Infinity);

    center = new Vector3(0, 0, 0);

    uniforms: { [key: string]: any } = {};

    _size = 1;
    //@ts-ignore
    set size(v: number) {
        this._size = v;
    }

    //@ts-ignore
    get size() {
        this.uniforms.progress.value = this.progress;
        this.uniforms.v3size.value.copy(this.v3size);// 模型大小
        this.uniforms.center.value.copy(this.center);// 模型大小
        return this._size;
    }

    onBeforeCompile(shader: WebGLProgramParametersWithUniforms, renderer: WebGLRenderer) {
        this.uniforms = Object.assign(shader.uniforms, {
            progress: { value: -Infinity }, // 粒子散开的进度
            v3size: { value: new Vector3(0, 0, 0) }, // 模型大小
            center: { value: new Vector3(0, 0, 0) }, // 中心位置
        });
        shader.vertexShader = this.vertexShader;
        shader.fragmentShader = this.fragmentShader;
    }

}